﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using Vbyte.SharpOrm.SqlDb;

namespace Vbyte.SharpOrm.Adapter
{
    /// <summary>
    /// 可重用的Sql构建抽象类
    /// </summary>
    public abstract class SqlBuilderBase : ISqlBuilderAdapter
    {
        #region ISqlBuilderAdapter 成员
        private string[] _fieldNames = new string[0];
        /// <summary>
        /// 获取或设置顺序字段名称集合
        /// </summary>
        /// <value></value>
        public string[] FieldNamesList
        {
            get
            {
                return _fieldNames;
            }
            set
            {
                _fieldNames = value;
            }
        }

        private string[] _fieldValues = new string[0];
        /// <summary>
        /// 获取或设置顺序字段的值集合(参数占位名或实际值)
        /// </summary>
        /// <value></value>
        public string[] FieldValuesList
        {
            get
            {
                return _fieldValues;
            }
            set
            {
                _fieldValues = value;
            }
        }

        private string[] _customValueSet = new string[0];
        /// <summary>
        /// 获取或设置制定字段的值集合(SQL Update)
        /// </summary>
        /// <value></value>
        public string[] CustomValueSetList
        {
            get
            {
                return _customValueSet;
            }
            set
            {
                _customValueSet = value ;
            }
        }

        /// <summary>
        /// 条件约束(where)
        /// </summary>
        /// <value></value>
        public virtual string SqlCondition
        {
            get;
            set;
        }

        /// <summary>
        /// 分组约束(Group by)
        /// </summary>
        /// <value></value>
        public virtual string SqlGroupBy
        {
            get;
            set;
        }

        /// <summary>
        /// 排序约束(Order By)
        /// </summary>
        /// <value></value>
        public virtual string SqlOrderBy
        {
            get;
            set;
        }

        private string _sqlLimit = "";
        /// <summary>
        /// 数据获取限制(TOP)
        /// </summary>
        /// <value></value>
        public virtual string SqlLimit
        {
            get
            {
                if (_sqlLimit != string.Empty)
                {
                    _sqlLimit = String.Concat(" TOP " , _maxRows, " ");
                }
                return _sqlLimit;
            }
            set
            {
                _sqlLimit = value;
            }
        }

        /// <summary>
        /// 获取或设置SQL语句管理的数据表名（或视图、联合查询SQL表）
        /// </summary>
        /// <value></value>
        public virtual string VirtualTable
        {
            get;
            set;
        }

        protected int _maxRows = 1;

        /// <summary>
        /// 设置返回记录的最大条数
        /// </summary>
        /// <param name="imaxRows">最大条数</param>
        public void SetRecordLimit(int imaxRows)
        {
            _maxRows = imaxRows;
        }

        /// <summary>
        /// 获取常用SQL语句的格式化定义
        /// </summary>
        /// <param name="cmdType">SQL数据表中单行命令类型</param>
        /// <returns>SQL语句的格式化定义</returns>
        public virtual string GetSqlFormatText(SQLRowCommandType cmdType)
        {
            string fmt = "";
            switch (cmdType)
            {
                case SQLRowCommandType.Insert:
                    fmt = "Insert into {VirtualTable}({FieldNamesList}) values({FieldValuesList})";
                    break;
                case SQLRowCommandType.Select:
                    fmt = "Select {SqlLimit}{FieldNamesList} from {VirtualTable} {SqlCondition} {SqlGroupBy} {SqlOrderBy}";
                    break;
                case SQLRowCommandType.Update:
                    fmt = "Update {VirtualTable} Set {CustomValueSetList} {SqlCondition} {SqlGroupBy} {SqlOrderBy}";
                    break;
                case SQLRowCommandType.Delete:
                    fmt = "Delete from {VirtualTable} {SqlCondition} {SqlGroupBy} {SqlOrderBy}";
                    break;
                default:
                    break;
            }
            return fmt;
        }

        /// <summary>
        /// 目标SQL构建格式化语句中的关键词集合
        /// </summary>
        /// <returns>关键词集合</returns>
        public virtual string[] GetFormatKeys()
        {
            return "{SqlLimit} {VirtualTable} {FieldNamesList} {FieldValuesList} {SqlCondition} {SqlGroupBy} {SqlOrderBy} {CustomValueSetList}".Split(' ');
        }

        /// <summary>
        /// 构建命令适配的SQL文本
        /// </summary>
        /// <param name="entry">ORM操作实例原型</param>
        /// <param name="cmdType">SQL数据表中单行命令类型</param>
        /// <param name="isSingleRow">是否时单行操作，如TOP 1等。</param>
        /// <returns>目标SQL语句</returns>
        public virtual string BuildCommandText(TableEntry entry, SQLRowCommandType cmdType, bool isSingleRow)
        {
            string[] DictItem = GetFormatKeys();
            string sqlFormat = GetSqlFormatText(cmdType);
            if (cmdType == SQLRowCommandType.Select && isSingleRow) SetRecordLimit(1);

            string propName = string.Empty, sqlValue = string.Empty;
            Type buildType = this.GetType();
            foreach (string item in DictItem)
            {
                propName = item.Trim('{', '}');
                sqlValue = string.Empty;
                PropertyInfo Pi = buildType.GetProperty(propName);
                if (Pi != null)
                {
                    object pVal = Pi.GetGetMethod().Invoke(this, null);
                    if (pVal != null)
                    {
                        if (Pi.PropertyType == typeof(string[]))
                        {
                            sqlValue = string.Join(" , ", (string[])pVal);
                        }
                        else
                        {
                            sqlValue = pVal.ToString();
                        }
                    }
                }
                sqlFormat = sqlFormat.Replace(item, sqlValue);
            }
            return sqlFormat;
        }


        /// <summary>
        /// 是否实现了约束的表达式语句构建
        /// </summary>
        /// <returns></returns>
        public abstract bool HasImplementConstraintExp();

        /// <summary>
        /// 构建SQL约束表达式
        /// </summary>
        /// <param name="build">实现了约束表达式构建的实例</param>
        /// <param name="dbOwner">数据库所有者占位前缀</param>
        /// <param name="tableName">数据库表名</param>
        /// <param name="columnName">涉及到的列名</param>
        /// <returns>最终的约束表达式语句</returns>
        public abstract string BuildConstraintExpression(ISqlConstraintExpBuild build, string dbOwner, string tableName, string columnName);

        #endregion
    }

}
